#pragma once
#include <highgui.h>
#include "stdlib.h"
#include "FrameKey.h"
#include "BasePatch.h"
#include "LivingPatch.h"

using namespace std;

class Patch : public BasePatch, public LivingPatch<Patch>
{
protected:
	static const int R = 33;
	unsigned char _data[R*R];

	void copyToLocal(CvMat* derivative, int x, int y)
	{
		unsigned char* d = _data;
		unsigned char* s = derivative->data.ptr + y*derivative->cols + x;
		for (int i = 0; i < R; i++, d += R, s += derivative->cols)
			memcpy(d,s,R);
	}

	Patch(FrameKey* key, CvMat* derivative, int x, int y) :  BasePatch(key, x, y), LivingPatch(key, x, y)
	{
		copyToLocal(derivative, x, y);		
	}

	virtual void OnUpdate(Patch* patch)
	{
		memcpy(_data, patch->_data, R*R);
	}

public:

	static Patch* Create(FrameKey* key, CvMat* derivative, int x, int y)
	{
		if ((x + R < derivative->width - 1) && (y + R < derivative->height - 1))
			return new Patch(key, derivative, x, y);
		else
			return NULL;
	}

	template <typename T>
	T* GetMostSimilar(vector<T*>* paths, float maxDistance)
	{		
		T* biggest = NULL;
		int biggestSum = 0;

		for(vector<T*>::const_iterator it = paths->begin(); it != paths->end(); ++it)
		{
			T* patch = *it;

			// no far from me
			if ((abs(patch->_point.x - _point.x) < maxDistance) && (abs(patch->_point.y - _point.y) < maxDistance))
			{
				int sum = 0;
				// calculate similarity summ
				for (int i = 0; i < R*R; i++)
					sum += patch->_data[i] == _data[i];

				// that is most similarity
				if (sum > R*R*50/100)
				{
					if (biggest == NULL || biggestSum < sum)
					{					
						biggestSum = sum;
						biggest = patch;
					}
				}
			}
		}

		return biggest;
	}
};

